package com.ssd.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Strings;
import com.ssd.common.VMSystem;
import com.ssd.emq.utils.BCrypt;
import com.ssd.emq.utils.JWTUtil;
import com.ssd.entity.Role;
import com.ssd.entity.User;
import com.ssd.entity.dto.LoginReq;
import com.ssd.entity.vo.LoginResp;
import com.ssd.exception.LogicException;
import com.ssd.mapper.UserMapper;
import com.ssd.service.IPartnerService;
import com.ssd.service.IRoleService;
import com.ssd.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssd.service.SmsService;
import com.ssd.utils.StringUtils;
import com.ssd.view.BaseResponse;
import com.ssd.view.TokenObject;
import com.ssd.viewmodel.Pager;
import com.ssd.viewmodel.UserWork;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-11-14
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Resource
    private IRoleService roleService;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private IPartnerService partnerService;

    @Resource
    private SmsService smsService;
    @Override
    public BaseResponse add(User user) {
        //1.根据角色id查询角色信息
        Role role = roleService.getById(user.getRoleId());
        if (role == null) throw new LogicException("角色不存在！");
        user.setStatus(1);//状态
        user.setRoleCode(role.getRoleCode());//角色code
        user.setRegionName(role.getRoleName());//角色名称
        return new BaseResponse(save(user));
    }

    @Override
    public Pager<User> findPage(Integer pageIndex, Integer pageSize, String userName, Integer roleId, Boolean isRepair) {
        //1.设置分页参数
        Page<User> page = new Page<>(pageIndex, pageSize);
        //2.设置查询条件
        Page<User> pages = lambdaQuery()
                .like(!userName.equals(""), User::getUserName, userName)
                .eq(roleId > 0, User::getRoleId, roleId)
                .page(page);
        //3.隐私密码
        pages.getRecords().forEach(item -> item.setPassword("******"));
        return Pager.build(pages);
    }

    @Override
    public BaseResponse<LoginResp> login(LoginReq req) throws IOException {
        if (req.getLoginType() == VMSystem.LOGIN_ADMIN) {
            //管理员登录
            return new BaseResponse<>(this.adminLogin(req));
        } else if (req.getLoginType() == VMSystem.LOGIN_EMP) {
            //运维运营人员登录
            return  new BaseResponse<>(this.empLogin(req));
        } else if (req.getLoginType() == VMSystem.LOGIN_PARTNER) {
            //合作商登录
            return new BaseResponse<>(partnerService.login(req));
        }
        LoginResp resp = new LoginResp();
        resp.setSuccess(false);
        resp.setMsg("不存在该账号！");
        return new BaseResponse<>(resp);
    }

    /**
     * 生成手机验证码
     * @param mobile 手机号
     */
    @Override
    public void sendCode(String mobile) {
        //查询redis中是否存在该手机号的验证码
        String code = redisTemplate.opsForValue().get(mobile);
        if (Strings.isNullOrEmpty(code)) {
            //生成6位随机数
            code = String.valueOf((int) (Math.random() * 900000 + 100000));
            //将验证码存入redis中，并设置过期时间
            redisTemplate.opsForValue().set(mobile, code, 60 * 5);
            log.info("短信验证码："+code);
            //发送短信
            smsService.sendSms(mobile,code);
        }
    }

    /**
     * 获取某区域下运维人员列表
     * @param regionId 区域id
     * @return
     */
    @Override
    public BaseResponse<List<User>> getOperatorList(Long regionId) {
        //1.查询列表
        List<User> users = lambdaQuery().eq(User::getRoleCode, "1002")
                .eq(User::getRegionId, regionId)
                .eq(User::getStatus, 1).list();
        //2.判断集合不为空不为null

        return new BaseResponse<>(users.stream().map(v->{
            v.setPassword("******");
            return v;
        }).collect(Collectors.toList()));
    }

    /**
     * 获取某区域下维修人员列表
     * @param regionId 区域id
     * @return
     */
    @Override
    public BaseResponse<List<User>> getRepairerList(Long regionId) {
        //1.查询列表
        List<User> users = lambdaQuery().eq(User::getRoleCode, "1003")
                .eq(User::getRegionId, regionId)
                .eq(User::getStatus, 1).list();
        //2.判断集合不为空不为null

        return new BaseResponse<>(users.stream().map(v->{
            v.setPassword("******");
            return v;
        }).collect(Collectors.toList()));
    }

    /**
     * 搜索用户工作量列表
     * @param pageIndex 当前页
     * @param pageSize 每页大小
     * @param userName 用户名
     * @param roleCode 角色code
     * @return
     */
    @Override
    public BaseResponse<Pager<UserWork>> searchUserWork(long pageIndex, long pageSize, String userName, String roleCode) {
        //查询用户
        Page<User> page = new Page<>(pageIndex, pageSize);
        Page<User> userPage = lambdaQuery()
                .like(!userName.equals(""), User::getUserName, userName)
                .between(StringUtils.isEmpty(roleCode), User::getRoleCode, "1003", "1002")
                .eq(StringUtils.isNotEmpty(roleCode), User::getRoleCode, roleCode)
                .page(page);
        //查询用户工作量，需要远程调用工单服务
        List<UserWork> collect = userPage.getRecords()
                .stream().map(u -> {
                    LocalDateTime now = LocalDateTime.now();
                    LocalDateTime start = LocalDateTime.of(now.getYear(), now.getMonth(), 1, 0, 0, 0);
                    //TODO 远程调用工单服务，根据用户id和时间范围获取用户工作量

                    UserWork userWork = new UserWork();
                    //设置用户名称
                    userWork.setUserName(u.getUserName());
                    //设置角色名称
                    userWork.setRoleName(u.getRoleCode().equals("1003") ? "维修人员" : "运营人员");
                    //设置手机号码
                    userWork.setMobile(u.getMobile());
                    return userWork;
                }).collect(Collectors.toList());

        //封装分页对象
        Pager<UserWork> result= Pager.buildEmpty();
        result.setPageIndex(pageIndex);
        result.setPageSize(pageSize);
        result.setTotalCount( userPage.getTotal());
        //计算总页数
//        result.setTotalPage(Math.ceil(userPage.getTotal()*1.0/pageSize));
        result.setCurrentPageRecords( collect );
        return new BaseResponse<>(result);
    }

    /**
     * 运维人员登录
     * @param req
     */
    private LoginResp empLogin(LoginReq req) throws IOException {
        //1.初始化登录响应对象，并默认设置成功登录为false
        LoginResp resp = new LoginResp();
        resp.setSuccess(false);
        //2.从redis中获取对应手机号的验证码
        String code = redisTemplate.boundValueOps(req.getMobile()).get();
        if (Strings.isNullOrEmpty(code)) {
            resp.setMsg("验证码已过期！");
            return resp;
        }
        if (!code.equals(req.getCode())) {
            resp.setMsg("验证码不正确！");
            return resp;
        }
        //3.根据手机号查询用户信息
        User user = lambdaQuery().eq(User::getMobile, req.getMobile()).one();
        if (user == null){
            resp.setMsg("用户不存在！");
            return resp;
        }
        if (user.getStatus() == 0) {
            resp.setMsg("账号已禁用！");
            return resp;
        }
        //属性拷贝
        BeanUtil.copyProperties(user, resp);
        resp.setSuccess(true);
        //是运维人员
        resp.setRepair(true);
        //生成token
        TokenObject tokenObject = new TokenObject();
        // 设置用户ID
        tokenObject.setUserId(user.getId());
        // 设置手机号，这里注释掉的代码是设置用户名，可能用于测试
        tokenObject.setMobile(user.getMobile());
        //设置用户名称
        tokenObject.setUserName(user.getUserName());
        //设置登录类型
        tokenObject.setLoginType(VMSystem.LOGIN_EMP);
        // 通过Token对象和密钥生成JWT
        String token = JWTUtil.createJWTByObj(tokenObject,user.getMobile() + VMSystem.JWT_SECRET);
        // 将生成的JWT设置到响应对象中
        resp.setToken(token);
        // 设置登录成功消息
        resp.setMsg("登录成功");

        return resp;
    }

    /**
     * 管理员登录
     *
     * @param req
     */
    private LoginResp adminLogin(LoginReq req) throws IOException {
        LoginResp resp = new LoginResp();
        resp.setSuccess(false);
        //1.从redis中取出验证码
        String code = redisTemplate.boundValueOps(req.getClientToken()).get();
        //2.判断验证码是否正确
        if (Strings.isNullOrEmpty(code)) {
            resp.setMsg("验证码已过期！");
            return resp;
        }
        if (!code.equals(req.getCode())) {
            resp.setMsg("验证码不正确！");
            return resp;
        }
        //3.验证账号密码是否正确
        User user = lambdaQuery().eq(User::getLoginName, req.getLoginName()).one();
        if (user == null) {
            resp.setMsg("账户名或密码错误！");
            return resp;
        }
        boolean loginSuccess = BCrypt.checkpw(req.getPassword(), user.getPassword());
        if (!loginSuccess) {
            resp.setMsg("账号名或密码错误！");
            return resp;
        }
        //属性拷贝
        BeanUtil.copyProperties(user, resp);
        resp.setSuccess(true);
        //生成token
        TokenObject tokenObject = new TokenObject();
        // 设置用户ID
        tokenObject.setUserId(user.getId());
        // 设置手机号，这里注释掉的代码是设置用户名，可能用于测试
        tokenObject.setMobile(user.getMobile());
        //设置用户名称
        tokenObject.setUserName(user.getUserName());
        //设置登录类型
        tokenObject.setLoginType(VMSystem.LOGIN_ADMIN);
        // 通过Token对象和密钥生成JWT
        String token = JWTUtil.createJWTByObj(tokenObject, VMSystem.JWT_SECRET);
        // 将生成的JWT设置到响应对象中
        resp.setToken(token);
        resp.setUserId(user.getId());//用户id
        // 设置登录成功消息
        resp.setMsg("登录成功");
        return resp;
    }

}
